﻿using System;
using System.Collections.Generic;

namespace org.xisoft.game.utils.game.algorithms
{
    public class MulAlphaBetaAlgorithm<AI,Broad> : AiAlgorithm<Broad>
        where AI : AlphaBetaAlgorithm<Broad>, new()
        where Broad: ChessBoardBase
    {

        long alpha = -long.MaxValue / 2;

        public override MoveAction Search(Broad gobangBroad, int depth)
        {
            List<MoveAction> list = GetSortedAllCanMoves(gobangBroad);
            MoveAction bestMove = null;
            alpha = -long.MaxValue / 2;
            using (ThreadExecuter threadExecuter = new ThreadExecuter())
            {
                Action<MoveAction> searchAction = moveAction =>
                {
                    lock (this)
                    {
                        if (bestMove == null || bestMove.Score < moveAction.Score)
                        {
                            bestMove = moveAction;
                            alpha = bestMove.Score;
                        }
                    }
                };

                foreach (MoveAction moveAction in list)
                {
                    Broad broad = gobangBroad.Clone() as Broad;
                    broad.DoNextMove( moveAction);
                    SearchTask task = new SearchTask { moveAction = moveAction, aiChessboard = broad, callback = searchAction, parent=this };
                    threadExecuter.Execute(task.Run);
                    //task.Run();
                }

                threadExecuter.WaitAllFinish();
            }
            return bestMove;
        }


        public override bool? GetWinColor(Broad chessBoard)
        {
            return new AI().GetWinColor(chessBoard);
        }

        public override List<MoveAction> GetAllCanMoves(Broad broad)
        {
            return new AI().GetAllCanMoves(broad);
        }

        class SearchTask
        {
            public MoveAction moveAction;
            public Broad aiChessboard;
            public Action<MoveAction> callback;
            public MulAlphaBetaAlgorithm<AI, Broad> parent;

            public void Run()
            {
                AI ai = new AI();
                MoveAction action = ai.Search(aiChessboard,ai.MaxDeep-1, long.MinValue, -parent.alpha);
                if (action != null)
                    moveAction.Score -= action.Score;
                moveAction.Next = action;

                callback(moveAction);
            }
        }
    }
}
